package com.ruoyi.model.service.impl;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.model.domain.ModelTrainResult;
import com.ruoyi.model.service.IModelResultService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.data.redis.core.RedisTemplate;

import java.util.*;

/**
 * @author WeiHanQiang
 * @date 2025/06/06 11:29
 **/
@Service
public class ModelResultServiceImpl implements IModelResultService {
    @Autowired
    private RedisCache redisCache;

    @Autowired
    private ObjectMapper objectMapper;

    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    @Override
    public void cacheModelResult(ModelTrainResult result) {
        Map<String, String> cacheMap = new HashMap<>();
        cacheMap.put("latentVariableCount", String.valueOf(result.getLatentVariableCount()));
        cacheMap.put("Rc2", String.valueOf(result.getRc2()));
        cacheMap.put("RMSECV", String.valueOf(result.getRMSECV()));
        cacheMap.put("Rp2", String.valueOf(result.getRp2()));
        cacheMap.put("RMSEP", String.valueOf(result.getRMSEP()));
        cacheMap.put("RPD", String.valueOf(result.getRPD()));
        cacheMap.put("T_test", String.valueOf(result.getT_test()));
        cacheMap.put("T", String.valueOf(result.getT()));

        try {
            cacheMap.put("calibrationStandard", objectMapper.writeValueAsString(result.getCalibrationStandard()));
            cacheMap.put("calibrationPredicted", objectMapper.writeValueAsString(result.getCalibrationPredicted()));
            cacheMap.put("validationPredicted", objectMapper.writeValueAsString(result.getValidationPredicted()));
            cacheMap.put("coef", objectMapper.writeValueAsString(result.getCoef()));
        } catch (JsonProcessingException e) {
            throw new RuntimeException("序列化模型数据失败", e);
        }


        String uuid = UUID.randomUUID().toString();
        String detailKey = "model:train:" + result.getModelNo() + ":" + uuid;
        redisCache.setCacheMap(detailKey, cacheMap);
        String indexKey = "model:train:index:" + result.getModelNo();
        redisTemplate.opsForList().rightPush(indexKey, detailKey);
    }

    @Override
    public List<ModelTrainResult> getCachedModelResults(String modelNo) {
        String indexKey = "model:train:index:" + modelNo;
        List<String> detailKeys = redisTemplate.opsForList().range(indexKey, 0, -1);

        if (detailKeys == null || detailKeys.isEmpty()) {
            return Collections.emptyList();
        }

        List<ModelTrainResult> resultList = new ArrayList<>();
        ObjectMapper objectMapper = new ObjectMapper();

        for (String key : detailKeys) {
            Map<String, String> cacheMap = redisCache.getCacheMap(key);

            if (cacheMap == null || cacheMap.isEmpty()) {
                continue; // 跳过空缓存
            }

            ModelTrainResult result = new ModelTrainResult();
            result.setModelNo(modelNo);

            try {
                result.setLatentVariableCount(Integer.parseInt(cacheMap.getOrDefault("latentVariableCount", "0")));
                result.setRc2(Double.parseDouble(cacheMap.getOrDefault("Rc2", "0")));
                result.setRMSECV(Double.parseDouble(cacheMap.getOrDefault("RMSECV", "0")));
                result.setRp2(Double.parseDouble(cacheMap.getOrDefault("Rp2", "0")));
                result.setRMSEP(Double.parseDouble(cacheMap.getOrDefault("RMSEP", "0")));
                result.setRPD(Double.parseDouble(cacheMap.getOrDefault("RPD", "0")));
                result.setT_test(Double.parseDouble(cacheMap.getOrDefault("T_test", "0")));
                result.setT(Double.parseDouble(cacheMap.getOrDefault("T", "0")));

                result.setCalibrationStandard(objectMapper.readValue(
                        cacheMap.getOrDefault("calibrationStandard", "[]"),
                        new TypeReference<List<Double>>() {}));

                result.setCalibrationPredicted(objectMapper.readValue(
                        cacheMap.getOrDefault("calibrationPredicted", "[]"),
                        new TypeReference<List<Double>>() {}));

                result.setValidationPredicted(objectMapper.readValue(
                        cacheMap.getOrDefault("validationPredicted", "[]"),
                        new TypeReference<List<Double>>() {}));

                result.setCoef(objectMapper.readValue(
                        cacheMap.getOrDefault("coef", "[]"),
                        new TypeReference<List<Double>>() {}));
            } catch (Exception e) {
                throw new RuntimeException("反序列化模型数据失败，key: " + key, e);
            }

            resultList.add(result);
        }

        return resultList;
    }

    @Override
    public void deleteCachedModelResults(String modelNo) {
        List<String> keys = redisTemplate.opsForList().range("model:train:index:" + modelNo, 0, -1);
        redisTemplate.delete(keys);
        redisTemplate.delete("model:train:index:" + modelNo);
    }


}
